unit udlgCustomDlgForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.Buttons;

type
  TdlgCustomDlgForm = class(TForm)
    pTop: TPanel;
    Shape1: TShape;
    Shape2: TShape;
    lCaption: TLabel;
    pButtom: TPanel;
    btOk: TSpeedButton;
    btClose: TSpeedButton;
    shBevel: TShape;
    fadeTimer: TTimer;
    procedure btCloseClick(Sender: TObject);
    procedure pTopMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure fadeTimerTimer(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure btOkClick(Sender: TObject);
  private
    FSysShadowHandle: THandle;
  protected
    FButtonClicked: integer;

    procedure FixSysShadowOrder();
  public
    constructor Create(AOwner: TComponent); override;

    procedure CreateParams(var Params: TCreateParams); override;
    procedure WMWindowPosChanged(var Message: TWMWindowPosChanged); message WM_WINDOWPOSCHANGED;

    property ButtonClicked: integer read FButtonClicked;
  end;

implementation

{$R *.dfm}

{ TfrmCustomDlgForm }

procedure TdlgCustomDlgForm.FixSysShadowOrder();

  function FindSysShadowOrderProc(WindowHandle: HWND; // handle to window
    Form: TdlgCustomDlgForm // application-defined value, 32-bit
    ): BOOL; stdcall;
  var
    Buffer: array [0 .. 255] of char;
    Rect: TRect;
  begin
    Result := True;
    if IsWindowVisible(WindowHandle) then
    begin
      // this code  search for SysShadow window created for this window.
      GetClassName(WindowHandle, Buffer, 255);
      if 0 <> AnsiStrComp(Buffer, PChar('SysShadow')) then
        Exit;

      GetWindowRect(WindowHandle, Rect);
      if (Rect.Left <> Form.Left) or (Rect.Top <> Form.Top) then
        Exit;

      Form.FSysShadowHandle := WindowHandle;
      // stop enumeration
      Result := False;
    end;
  end;

begin
  if not(csDesigning in ComponentState) and
    ((GetClassLong(Handle, GCL_STYLE) and CS_DROPSHADOW) = CS_DROPSHADOW)
    and IsWindowVisible(Handle) then
  begin
    // for speed, proper SysShadow handle is cached
    if FSysShadowHandle = 0 then
      EnumThreadWindows(GetCurrentThreadID(), @FindSysShadowOrderProc,
        lParam(Self));
    // if SysShadow exists, change its z-order, and place it directly below this window
    if FSysShadowHandle <> 0 then  begin
      if Tag <> 255 then begin
        Tag:= 255;
        SetWindowPos(FSysShadowHandle, Handle, 0, 0, 0, 0,
          {SWP_NOACTIVATE or} SWP_NOMOVE or SWP_NOOWNERZORDER or SWP_NOSIZE)
      end else
        SetWindowPos(FSysShadowHandle, Handle, 0, 0, 0, 0,
          SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOOWNERZORDER or SWP_NOSIZE);
    end;
  end;
end;

procedure TdlgCustomDlgForm.btCloseClick(Sender: TObject);
begin
  Close;
end;

procedure TdlgCustomDlgForm.btOkClick(Sender: TObject);
begin
  FButtonClicked:= IDYES;
end;

constructor TdlgCustomDlgForm.Create(AOwner: TComponent);
begin
  inherited;
  FButtonClicked:= IDNO;
end;

procedure TdlgCustomDlgForm.CreateParams(var Params: TCreateParams);
begin
  inherited;

   if (Win32Platform = VER_PLATFORM_WIN32_NT) and
     (
       (Win32MajorVersion > 5) or
         (
           (Win32MajorVersion = 5) and (Win32MinorVersion >= 1)
         )
     )
   then
     Params.WindowClass.Style := Params.WindowClass.Style or CS_DROPSHADOW;
end;

procedure TdlgCustomDlgForm.pTopMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  ReleaseCapture;
  Perform(WM_SYSCOMMAND, $F012, 0);
end;

procedure TdlgCustomDlgForm.WMWindowPosChanged(var Message: TWMWindowPosChanged);
begin
  FixSysShadowOrder();
  inherited;
end;

procedure TdlgCustomDlgForm.fadeTimerTimer(Sender: TObject);
const
  FADE_OUT_SPEED = 60;
var
  newBlendValue : integer;
begin
  if AlphaBlendValue > 0 then begin
    newBlendValue := -1 * FADE_OUT_SPEED + AlphaBlendValue;
    if newBlendValue >  0 then
      AlphaBlendValue := newBlendValue
    else
      AlphaBlendValue := 0;
  end else begin
    fadeTimer.Enabled := false;
    Close;
  end;
end;

procedure TdlgCustomDlgForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  CanClose := True;
  {
  if AlphaBlend then
    CanClose := True
  else begin
    AlphaBlendValue := 255;
    AlphaBlend:= True;
    fadeTimer.Enabled := true;
    CanClose := false;
  end;
  }
end;

end.
